﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FlashCards.Model;

namespace FlashCards.NeuralNetworks.Utils
{
    public class NeuralNetworkManager
    {
        private NeuralNetwork _network;
        private List<Dictionary<int, double>> _inputs;
        private List<double[]> _learningSet;
        private int _userId;

        public NeuralNetworkManager(Repeat repeat)
        {
            if(_network == null)
                _network = new NeuralNetwork(2, repeat.FlashcardSet.Flashcards.Count, 4, repeat.FlashcardSetId, repeat.FlashcardSet.Flashcards.Select(x => x.FlashcardId).ToList());
            _learningSet = new List<double[]>();
            _inputs = new List<Dictionary<int, double>>();
            _userId = repeat.UserId;

            var flashcards = repeat.RepeatItems.Where(x => !x.IsCopied).Select(x => x.Flashcard).ToList();

            for (int i = 0; i < flashcards.Count; i++)
            {
                var dict = new Dictionary<int, double>();
                dict.Add(flashcards[i].FlashcardId, 1);
                for (int j = 0; j < flashcards.Count; j++)
                {
                    if (j == i)
                        continue;
                    dict.Add(flashcards[j].FlashcardId, 0);
                }
                _inputs.Add(dict);

                var index = repeat.RepeatItems.FirstOrDefault(x => x.FlashcardId == flashcards[i].FlashcardId).RepeatMark;

                _learningSet.Add(new double[4]);
                _learningSet[i][index] = 1;
            }
        }

        public NeuralNetworkManager(Repeat repeat, NeuralNetwork network)
            : this(repeat)
        {
            _network = network;
        }

        public void TrainNetworkForUnknown(int maxIterations, double maxError)
        {
            var answers = new List<double[]>();
            foreach (var item in _inputs)
            {
                var answer = new double[4];
                answer[0] = 1;
                answers.Add(answer);
            }

            _network.TrainWholeSet(_inputs, answers, maxIterations, maxError);
        }

        public void TrainNetwork(int maxIterations, double maxError)
        {
            _network.TrainWholeSet(_inputs, _learningSet, maxIterations, maxError, true);
        }

        public Model.NeuralNetwork GetNetworkModel()
        {
            var network = _network.ToEntity();
            network.UserId = _userId;
            return network;
        }

        public Dictionary<int, double[]> GetResult()
        {
            var results = new Dictionary<int ,double[]>();
            foreach (var input in _inputs)
            {
                var flashcardId = input.FirstOrDefault(x => x.Value == 1);
                results.Add(flashcardId.Key, _network.GetResult(input));
            }

            return results;
        }
    }
}
